package com.netty.demo.server.utils;

import com.netty.demo.server.loader.DynamicClassLoader;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.PropertyUtilsBean;

import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * 动态类反射工具类
 *
 * @author Administrator 余秀良
 * @version 1.0
 * <p>date: 2019年09月18日  17:39 </p>
 * <p>address: 四川成都 </p>
 */
@Slf4j
public final class DynamicClassReflectUtil {

    public static Object getDynamicClass(Map<String, Object> addProperties) {
        Object object = new Object();
        PropertyUtilsBean propertyUtilsBean = new PropertyUtilsBean();
        PropertyDescriptor[] descriptors = propertyUtilsBean.getPropertyDescriptors(object);
        Map<String, Class> propertyMap = new HashMap<>(16);
        for (PropertyDescriptor d : descriptors) {
            if (!"class".equalsIgnoreCase(d.getName())) {
                propertyMap.put(d.getName(), d.getPropertyType());
            }
        }
        addProperties.forEach((k, v) -> propertyMap.put(k, v.getClass()));
        DynamicClass dynamicBean = new DynamicClass(object.getClass(), propertyMap);
        propertyMap.forEach((k, v) -> {
            try {
                if (!addProperties.containsKey(k)) {
                    dynamicBean.setProperty(k, propertyUtilsBean.getNestedProperty(object, k));
                }
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                e.printStackTrace();
            }
        });
        addProperties.forEach((k, v) -> {
            try {
                dynamicBean.setProperty(k, v);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                e.printStackTrace();
            }
        });
        return dynamicBean.getClazz();
    }

    /**
     * 根据属性，获取get方法
     *
     * @param object 对象
     * @param name   属性名
     * @return 返回属性的值
     */
    public static Object getGetMethod(Object object, String name) {
        Method[] methods = object.getClass().getMethods();
        for (Method method : methods) {
            if (("get" + name).toLowerCase().equals(method.getName().toLowerCase())) {
                try {
                    return method.invoke(object);
                } catch (IllegalAccessException | InvocationTargetException e) {
                    e.printStackTrace();
                    return null;
                }
            }
        }
        return null;
    }

    /**
     * 动态添加方法
     *
     * @param method 创建方法的字符串 如："public String test(){return "hello";}"
     * @param clazz  需要动态增加方法的类
     * @return {@link T}
     * @author 余秀良
     * @version 1.0
     * <p>  date: 2019 - 09 - 19  11:37    </p>
     * <p>  address: 四川成都  </p>
     */
    public static <T> Object addMethod(String method, T clazz) {
        DynamicClassLoader dynamicClassLoader = DynamicClassLoader.getInstance();
        return dynamicClassLoader.get(method, clazz);
    }
}
